package com.dingreading.cloud.common.util.alipay;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.*;
import com.alipay.api.request.*;
import com.alipay.api.response.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 支付宝调用方法
 */
public class AliPayApi {

    /**
     * 电脑网站支付
     * https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.dfHHR3&treeId=203&articleId=105285&docType=1
     *
     * @param response  http
     * @param model     model
     * @param returnUrl 通知回调地址
     * @param notifyUrl 通知回调地址
     */
    public static void pagePay(
            HttpServletResponse response, AlipayTradePagePayModel model, String returnUrl, String notifyUrl
    ) throws AlipayApiException, IOException {
        // 设置wap支付参数
        model.setPassbackParams("1");
        model.setProductCode("FAST_INSTANT_TRADE_PAY");
        // 取值范围：1m～15d。m-分钟，h-小时，d-天，1c-当天（1c-无论交易何时创建，都在0点关闭）.该参数数值不接受小数点， 如 1.5h，可转换为 90m。
        model.setTimeoutExpress("30m");
        // 发起wap支付
        AlipayTradePagePayResponse payResponse = pagePayRequest(model, returnUrl, notifyUrl);
        if (payResponse.isSuccess()) {
            String form = payResponse.getBody();
            response.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
            // 直接将完整的表单html输出到页面
            response.getWriter().write(form);
            response.getWriter().flush();
            response.getWriter().close();
        } else {
            System.out.println("支付宝WAP支付 = " + payResponse.getMsg());
        }
    }

    /**
     * 电脑网站支付处理
     *
     * @param model     model
     * @param returnUrl 通知回调地址
     * @param notifyUrl 通知回调地址
     * @return String
     */
    public static AlipayTradePagePayResponse pagePayRequest(AlipayTradePagePayModel model, String returnUrl, String notifyUrl) throws AlipayApiException, IOException {
        // 创建API对应的request
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(returnUrl);
        // 在公共参数中设置回跳和通知地址
        alipayRequest.setNotifyUrl(notifyUrl);
        // 填充业务参数
        alipayRequest.setBizModel(model);

        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.SERVER_URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY,
                AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
        // 调用SDK生成表单
        return alipayClient.pageExecute(alipayRequest);
    }

    /**
     * 电脑网站支付
     * https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.dfHHR3&treeId=203&articleId=105285&docType=1
     *
     * @param response  http
     * @param model     model
     * @param returnUrl 通知回调地址
     * @param notifyUrl 通知回调地址
     */
    public static void pagePay(
            HttpServletResponse response, AlipayTradePagePayModel model, String returnUrl, String notifyUrl, String appid, String priKey, String pubKey
    ) throws AlipayApiException, IOException {
        // 设置wap支付参数
        model.setPassbackParams("1");
        model.setProductCode("FAST_INSTANT_TRADE_PAY");
        // 取值范围：1m～15d。m-分钟，h-小时，d-天，1c-当天（1c-无论交易何时创建，都在0点关闭）.该参数数值不接受小数点， 如 1.5h，可转换为 90m。
        model.setTimeoutExpress("30m");

        // 创建API对应的request
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(returnUrl);
        // 在公共参数中设置回跳和通知地址
        alipayRequest.setNotifyUrl(notifyUrl);
        // 填充业务参数
        alipayRequest.setBizModel(model);
        // 发起wap支付
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.SERVER_URL, appid, priKey,
                AlipayConfig.FORMAT, AlipayConfig.CHARSET, pubKey, AlipayConfig.SIGNTYPE);
        // 调用SDK生成表单
        AlipayTradePagePayResponse payResponse = alipayClient.pageExecute(alipayRequest);
        if (payResponse.isSuccess()) {
            String form = payResponse.getBody();
            response.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
            // 直接将完整的表单html输出到页面
            response.getWriter().write(form);
            response.getWriter().flush();
            response.getWriter().close();
        } else {
            System.out.println("支付宝WAP支付 = " + payResponse.getMsg());
        }
    }

    /**
     * WAP支付
     * https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.dfHHR3&treeId=203&articleId=105285&docType=1
     *
     * @param response  http
     * @param model     model
     * @param returnUrl 通知回调地址
     * @param notifyUrl 通知回调地址
     */
    public static void wapPay(HttpServletResponse response, AlipayTradeWapPayModel model, String returnUrl, String notifyUrl) throws AlipayApiException, IOException {
        // 设置wap支付参数
        model.setPassbackParams("1");
        model.setProductCode("QUICK_WAP_PAY");
        // 取值范围：1m～15d。m-分钟，h-小时，d-天，1c-当天（1c-无论交易何时创建，都在0点关闭）.该参数数值不接受小数点， 如 1.5h，可转换为 90m。
        model.setTimeoutExpress("30m");
        // 发起wap支付
        AlipayTradeWapPayResponse payResponse = wapPayRequest(model, returnUrl, notifyUrl);
        if (payResponse.isSuccess()) {
            String form = payResponse.getBody();
            response.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
            // 直接将完整的表单html输出到页面
            response.getWriter().write(form);
            response.getWriter().flush();
            response.getWriter().close();
        } else {
            System.out.println("支付宝WAP支付 = " + payResponse.getMsg());
        }
    }

    /**
     * WAP支付
     *
     * @param model     model
     * @param returnUrl 通知回调地址
     * @param notifyUrl 通知回调地址
     * @return String
     */
    public static AlipayTradeWapPayResponse wapPayRequest(AlipayTradeWapPayModel model, String returnUrl, String notifyUrl) throws AlipayApiException, IOException {
        // 创建API对应的request
        AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();
        alipayRequest.setReturnUrl(returnUrl);
        // 在公共参数中设置回跳和通知地址
        alipayRequest.setNotifyUrl(notifyUrl);
        // 填充业务参数
        alipayRequest.setBizModel(model);

        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.SERVER_URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY,
                AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
        // 调用SDK生成表单
        return alipayClient.pageExecute(alipayRequest);
    }

    /**
     * WAP支付
     * https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.dfHHR3&treeId=203&articleId=105285&docType=1
     *
     * @param response  http
     * @param model     model
     * @param returnUrl 通知回调地址
     * @param notifyUrl 通知回调地址
     */
    public static void wapPay(
            HttpServletResponse response, AlipayTradeWapPayModel model, String returnUrl, String notifyUrl, String appid, String priKey, String pubKey
    ) throws AlipayApiException, IOException {
        // 设置wap支付参数
        model.setPassbackParams("1");
        model.setProductCode("QUICK_WAP_PAY");
        // 取值范围：1m～15d。m-分钟，h-小时，d-天，1c-当天（1c-无论交易何时创建，都在0点关闭）.该参数数值不接受小数点， 如 1.5h，可转换为 90m。
        model.setTimeoutExpress("30m");

        // 创建API对应的request
        AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();
        alipayRequest.setReturnUrl(returnUrl);
        // 在公共参数中设置回跳和通知地址
        alipayRequest.setNotifyUrl(notifyUrl);
        // 填充业务参数
        alipayRequest.setBizModel(model);
        // 发起wap支付
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.SERVER_URL, appid, priKey,
                AlipayConfig.FORMAT, AlipayConfig.CHARSET, pubKey, AlipayConfig.SIGNTYPE);
        // 调用SDK生成表单
        AlipayTradeWapPayResponse payResponse = alipayClient.pageExecute(alipayRequest);
        if (payResponse.isSuccess()) {
            String form = payResponse.getBody();
            response.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
            // 直接将完整的表单html输出到页面
            response.getWriter().write(form);
            response.getWriter().flush();
            response.getWriter().close();
        } else {
            System.out.println("支付宝WAP支付 = " + payResponse.getMsg());
        }
    }

    /**
     * APP支付
     *
     * @param response  http
     * @param model     model
     * @param returnUrl 通知回调地址
     * @param notifyUrl 通知回调地址
     */
    public static String appPay(HttpServletResponse response, AlipayTradeAppPayModel model, String returnUrl, String notifyUrl) throws AlipayApiException, IOException {
        AlipayTradeAppPayResponse appResponse = appPayStr(response, model, returnUrl, notifyUrl);
//        response.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
//        // 直接将完整的表单html输出到页面
//        response.getWriter().write(form);
//        response.getWriter().flush();
//        response.getWriter().close();
        return appResponse.getBody();
    }

    /**
     * APP支付
     *
     * @param response  http
     * @param model     model
     * @param returnUrl 通知回调地址
     * @param notifyUrl 通知回调地址
     * @return String
     */
    public static AlipayTradeAppPayResponse appPayStr(HttpServletResponse response, AlipayTradeAppPayModel model, String returnUrl, String notifyUrl) throws AlipayApiException, IOException {
        // 创建API对应的request
        AlipayTradeAppPayRequest alipayRequest = new AlipayTradeAppPayRequest();
        alipayRequest.setReturnUrl(returnUrl);
        // 在公共参数中设置回跳和通知地址
        alipayRequest.setNotifyUrl(notifyUrl);
        // 填充业务参数
        alipayRequest.setBizModel(model);
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.SERVER_URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY,
                AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
        // 调用SDK生成表单
        return alipayClient.execute(alipayRequest);
    }

    /**
     * 统一收单线下交易预创建
     * 扫码支付
     * https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.i0UVZn&treeId=193&articleId=105170&docType=1#s4
     *
     * @param model     model
     * @param notifyUrl 通知回调地址
     * @return {String}
     */
    public static String tradePrecreatePay(AlipayTradePrecreateModel model, String notifyUrl) throws AlipayApiException {
        AlipayTradePrecreateResponse response = tradePrecreatePayToResponse(model, notifyUrl);
        return response.getBody();
    }

    /**
     * 扫码支付
     *
     * @param model     model
     * @param notifyUrl 通知回调地址
     * @return response
     */
    public static AlipayTradePrecreateResponse tradePrecreatePayToResponse(AlipayTradePrecreateModel model, String notifyUrl) throws AlipayApiException {
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
        request.setBizModel(model);
        request.setNotifyUrl(notifyUrl);
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.SERVER_URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY,
                AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
        return alipayClient.execute(request);
    }

    /**
     * 统一收单线下交易预创建
     * 扫码支付
     * https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.i0UVZn&treeId=193&articleId=105170&docType=1#s4
     *
     * @param model     model
     * @param notifyUrl 通知回调地址
     * @return {String}
     */
    public static String tradePrecreatePay(AlipayTradePrecreateModel model, String notifyUrl, String appid, String priKey, String pubKey) throws AlipayApiException {
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
        request.setBizModel(model);
        request.setNotifyUrl(notifyUrl);
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.SERVER_URL, appid, priKey,
                AlipayConfig.FORMAT, AlipayConfig.CHARSET, pubKey, AlipayConfig.SIGNTYPE);
        AlipayTradePrecreateResponse response = alipayClient.execute(request);
        return response.getBody();
    }

    /**
     * 退款
     * https://doc.open.alipay.com/docs/api.htm?spm=a219a.7395905.0.0.SAyEeI&docType=4&apiId=759
     *
     * @param model model
     * @return {String}
     */
    public static String tradeRefund(AlipayTradeRefundModel model) throws AlipayApiException {
        AlipayTradeRefundResponse response = tradeRefundToResponse(model);
        return response.getBody();
    }

    /**
     * 退款
     *
     * @param model model
     * @return {AlipayTradeRefundResponse}
     */
    public static AlipayTradeRefundResponse tradeRefundToResponse(AlipayTradeRefundModel model) throws AlipayApiException {
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        request.setBizModel(model);
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.SERVER_URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY,
                AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
        return alipayClient.execute(request);
    }

    /**
     * 将异步通知的参数转化为Map
     *
     * @param request request
     * @return {Map<String, String>}
     */
    public static Map<String, String> toMap(HttpServletRequest request) {
        Map<String, String> params = new HashMap<String, String>(10);
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = iter.next();
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用;valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        return params;
    }

    /**
     * APP支付
     *
     * @param model
     * @param notifyUrl
     * @return {String}
     * @throws {AlipayApiException}
     */
    public static String startAppPay(AlipayTradeAppPayModel model, String notifyUrl) throws AlipayApiException {
        AlipayTradeAppPayResponse response = appPayToResponse(model, notifyUrl);
        return response.getBody();
    }

    /**
     * APP支付
     * https://doc.open.alipay.com/docs/doc.htm?treeId=54&articleId=106370&docType=1
     *
     * @param model
     * @param notifyUrl
     * @return {AlipayTradeAppPayResponse}
     * @throws {AlipayApiException}
     */
    public static AlipayTradeAppPayResponse appPayToResponse(AlipayTradeAppPayModel model, String notifyUrl) throws AlipayApiException {
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        request.setBizModel(model);
        request.setNotifyUrl(notifyUrl);
        //这里和普通的接口调用不同，使用的是sdkExecute
//        AlipayTradeAppPayResponse response = AliPayApiConfigKit.getAliPayApiConfig().getAlipayClient().sdkExecute(request);
//        return response;
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.SERVER_URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY,
                AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
        return alipayClient.sdkExecute(request);
    }

    /**
     * APP支付
     *
     * @param model
     * @param notifyUrl
     * @return {AlipayTradeAppPayResponse}
     * @throws {AlipayApiException}
     */
    @Deprecated
    public static AlipayTradeAppPayResponse appPay(AlipayTradeAppPayModel model, String notifyUrl) throws AlipayApiException {
        return appPayToResponse(model, notifyUrl);
    }

}
